/*
* @Author: z.p
* @Project: Zdotp
* @Date: 2024年12月30日
* @Description: actor中的单线程计时器, 可以通过添加keyFrame进行回调
*/

using Zdotp.Actor;
using Zdotp.Logs;
using Zdotp.ObjectPool;

namespace Zdotp.Timer;

public class ZTimer : ObjectBase
{
    public int TimerId;
    internal ActorBase MyActorBase;
    private readonly List<KeyFrame> _keyFrames = new();
    
    private Action<ZTimer> _overCallback;
    
    private readonly ZLogger _logger;

    private float _maxTimer;
    public bool IsLoop;

    private bool _isRun;
    private const float OffsetTime = 0.01f;
    
    public void AddKeyFrame(float time, Action action)
    {
        var keyFrame = ActorSystem.GetObj<KeyFrame>(kf =>
        {
            kf.Time = time;
            kf.Action = action;
            kf.IsTrigger = false;
        });
        if (keyFrame is null)
        {
            _logger.Error($"Get null keyFrame, type : {nameof(KeyFrame)}");
            return;
        }
        _keyFrames.Add(keyFrame);
    }
    
    public ZTimer()
    {
        _logger = LogHelper.CreateLogger($"ActorTimer");
    }
    
    public void Start(ActorBase actor)
    {
        if (_isRun)
        {
            _logger.Warn($"Timer {TimerId} is already running.");
            return;
        }
        
        if (_keyFrames.Count == 0)
        {
            _logger.Warn($"Timer {TimerId} has no key frames.");
            return;
        }

        _currentTimer = 0;

        foreach (var frame in _keyFrames) frame.IsTrigger = false;

        // 找到最大的时间
        _maxTimer = 0;
        foreach (var frame in _keyFrames)
        {
            if (frame.Time > _maxTimer) _maxTimer = frame.Time;
        }
        MyActorBase = actor;
        MyActorBase.StartTimer(this);
        _isRun = true;
    }

    private float _currentTimer;

    public void Update(float deltaTime)
    {
        if (!_isRun) return;
        _currentTimer += deltaTime;
        
        if (_currentTimer > _maxTimer + OffsetTime)
        {
            if (IsLoop)
            {
                _currentTimer -= _maxTimer;
                foreach (var keyFrame in _keyFrames) keyFrame.IsTrigger = false;
            }
            else
            {
                StopTimer();
            }
            return;
        }
        
        foreach(var keyFrame in _keyFrames)
        {
            if (keyFrame.IsTrigger || _currentTimer < keyFrame.Time - OffsetTime) continue;
            keyFrame.Action?.Invoke();
            keyFrame.IsTrigger = true;
        }
    }

    public void StopTimer()
    {
        if (!_isRun)
        {
            return;
        }
        
        _isRun = false;
        MyActorBase.StopTimer(this);
        ActorSystem.ReleaseObj(this);
    }

    private void Clear()
    {
        // 释放帧
        foreach (var keyFrame in _keyFrames)
        {
            ActorSystem.ReleaseObj(keyFrame);
        }
        _keyFrames.Clear();
        IsLoop = false;
    }

    public override void OnGet()
    {
        
    }

    public override void OnRelease()
    {
        Clear();
    }
}